package io.gitee.bowen_lee.lbwio.groupboss_and_groupworker;

import java.nio.channels.Channel;
import java.nio.channels.ServerSocketChannel;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 注册、轮询工具类
 * 
 * @author Bowen
 * @since 2022-01-06 15:54:14
 */
public class RegisterHandle {

  /**
   * R/W 工作者
   */
  static volatile SelectorThreadGroup worker = null;
  /**
   * accept 工作者
   */
  static volatile SelectorThreadGroup boss = null;

  /**
   * 初始化
   * 
   * @param stgBoss
   * @param stgWorker
   */
  public static void init(SelectorThreadGroup stgBoss, SelectorThreadGroup stgWorker) {
    if (worker == null) {
      synchronized (RegisterHandle.class) {
        if (worker == null) {
          worker = stgWorker;
        }
      }
    }

    if (boss == null) {
      synchronized (RegisterHandle.class) {
        if (boss == null) {
          boss = stgBoss;
        }
      }
    }

  }

  /**
   * 注册 使用开关来设置 线程执行顺序<br/>
   * 此外还可以使用 wakeup() 来取消selector.select() 的阻塞
   * 
   * @param server
   * @param xid
   */
  public static void serverRegister(Channel server) {
    // 检测是否有做初始化
    notEmpty();
    SelectorThread st;
    if (server instanceof ServerSocketChannel) {
      st = next(boss, boss.xid);
    } else {
      st = next(worker, worker.xid);
    }
    // 获取一个 selector ，把channel 送过去并且开启一次select()的阻塞，就不管了
    st.channel = server;
    st.selector.wakeup();

  }

  /**
   * 获取将要注册的 SelectorThread 对象<br/>
   * 此处 将会区分 boss 和worker 角色 <br/>
   * boss 只做 accept() 处理，worker做R/W处理
   * 
   * @param c Channel
   * @return
   */
  public static SelectorThread next(SelectorThreadGroup group, AtomicInteger xid) {
    // 取模的时候 去掉固定的boss 。
    int next = xid.incrementAndGet() % group.sts.length;
    System.out.println("next :" + next);
    return group.sts[next];
  }

  /**
   * 获取将要注册的 SelectorThread 对象<br/>
   * 此处 将会区分 boss 和worker 角色 <br/>
   * boss 只做 accept() 处理，worker做R/W处理
   * 
   * @param c Channel
   * @return
   */
  public static SelectorThread nextBoss() {
    notEmpty();
    // 取模的时候 去掉固定的boss 。
    return next(boss, boss.xid);
  }

  public static SelectorThread nextWorker() {
    notEmpty();
    // 取模的时候 去掉固定的boss 。
    return next(worker, worker.xid);
  }

  /**
   * 是否有执行过初始化
   */
  public static void notEmpty() {
    if (worker == null || boss == null) {
      synchronized (RegisterHandle.class) {
        throw new IllegalStateException("The 'RegisterUtil.init()' must be executed before use 'RegisterUtil' ");
      }
    }
  }

}
